package com.demo.web.security;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import java.util.Arrays;
import java.util.Collections;

@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {


    //数据源
    @Autowired
    private MyUserDetailServicelmpl myUserDetailServicelmpl;
    //认证成功
    @Autowired
    private AppAuthenticationSuccessHandler appAuthenticationSuccessHandler;
    //认证失败
    @Autowired
    private AppAuthenticationfailureHandler appAuthenticationfailureHandler;
    //认证失败
    @Autowired
    private AppAuthenticationLoginOutHandler appAuthenticationLoginOutHandler;
    //其他异常
    @Autowired
    private AppAccessDenyHandler appAccessDenyHandler;




    //账户认证 权限
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //账户认证交由自定义UserDetailsService去处理
        auth.userDetailsService(myUserDetailServicelmpl);
    }

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    //导入自定义登录过滤器 交给工厂管理
    @Bean
    LoginFilter loginFilter() throws Exception{
        LoginFilter loginFilter = new LoginFilter();
        loginFilter.setFilterProcessesUrl("/Login");
        loginFilter.setAuthenticationManager(authenticationManagerBean());
        loginFilter.setAuthenticationSuccessHandler(appAuthenticationSuccessHandler);
        return loginFilter;
    }


    //静态资源
    @Override
    public void configure(WebSecurity web) throws Exception {
        super.configure(web);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
//        //要访问/api/Student/下接口 必须拥有ROLE_student权限 如果没对url进行设置 则不用匹配权限  只需要进行认证 anyRequest().authenticated(); 然后接口进行认证
//        http.authorizeRequests().mvcMatchers("/api/Student/**").hasAnyAuthority("ROLE_student").mvcMatchers("/api/admin/**").hasAnyAuthority("ROLE_admin").and()
//                .antMatcher("/api/backstage/Login,/api/backstage/register,/api/backstage/hello")//登录请求放行
//                //拦截的请求
//        .antMatcher("/api/backstage/**").authenticated()
//                // 其余请求放行
//                .anyRequest().permitAll()
////                .anyRequest().authenticated()
        http.authorizeRequests()
                //下面代码决定放行的路径，可以填写多个
//                .antMatchers("/api/backstage/index/**", "/api/backstage/jobassembly/**").permitAll()
//                // 要拦截验证的请求
//                .antMatchers("/api/backstage/**").authenticated() 默认拦截所有请求。
//                // 其余请求放行
//                .anyRequest().permitAll().and().csrf().disable()//关闭CSRF保护即 可。
                // 其余请求全部认证
                .anyRequest().authenticated().and().formLogin().and()//关闭CSRF保护即可。
                //登录表单放行
                //登录成功处理的successHandler(appAuthenticationSuccessHandler)  登录失败处理的failureHandler(appAuthenticationfailureHandler) permitAll()所有请求都要认证
//                .formLogin().successHandler(appAuthenticationSuccessHandler).failureHandler(appAuthenticationfailureHandler).and()
//                //定义异常，认证异常 表达式处理.
                .exceptionHandling().authenticationEntryPoint((req, rep, e) -> {
                    rep.setContentType("application/json;charset=UTF-8");
                    rep.setStatus(HttpStatus.UNAUTHORIZED.value());
                    rep.getWriter().println("必须认证之后才能访问");
                }).and()
                .logout().logoutSuccessHandler(appAuthenticationLoginOutHandler)//退出成功处理
                .and()
                .exceptionHandling().accessDeniedHandler(appAccessDenyHandler).and().cors().configurationSource(corsConfigurationSource()).and().csrf().disable();//访问拒绝处理

        //替换登录
        http.addFilterAt(loginFilter(), UsernamePasswordAuthenticationFilter.class);

        //跨域替换


    }

    //跨域配置
    //跨域配置
    CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowedMethods(Collections.singletonList("*"));
        config.setAllowedHeaders(Collections.singletonList("*"));
        config.setAllowedOrigins(Collections.singletonList("*"));
        config.setAllowedOriginPatterns(Collections.singletonList("*"));
        config.setMaxAge(3600L);
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", config);
        return source;
    }


    //    密码编码
    //配置下默认加密bean
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}